package br.pucrio.inf.tamdera.prolog;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.common.util.EList;

import br.pucrio.inf.tamdera.ConceptDeclaration;
import br.pucrio.inf.tamdera.Constants;
import br.pucrio.inf.tamdera.Constraint;
import br.pucrio.inf.tamdera.ConstraintSetDeclaration;
import br.pucrio.inf.tamdera.MetricConstraint;
import br.pucrio.inf.tamdera.Paragraph;
import br.pucrio.inf.tamdera.RulesSpecification;
import br.pucrio.inf.tamdera.prolog.qbeans.PrologAntiDriftBean;
import br.pucrio.inf.tamdera.prolog.qbeans.PrologQueryBean;
import br.pucrio.inf.tamdera.prolog.utils.PrologIntegrationConstants;

public class PrologAntiDriftQueryVisitor {

	public PrologAntiDriftQueryVisitor() 
	{
		antiDriftQueries = new ArrayList<PrologQueryBean>();

	}


	protected List<PrologQueryBean> antiDriftQueries;


	protected void _generateQuery(final RulesSpecification spec) 
	{
		EList<Paragraph> paragraphs = spec.getParagraphs();
		for (Paragraph para : paragraphs )
		{
			generateQuery ( para );
		}
	}

	protected String getNameOfOperator ( final String operator )
	{
		if ( "<".equals(operator) )
		{
			return Constants.OPERATOR_LESS_THAN;
		}
		else if ( ">".equals(operator) )
		{
			return Constants.OPERATOR_GREATER_THAN;
		}
		else if ( ">=".equals(operator) )
		{
			return Constants.OPERATOR_GREATER_OR_EQUAL;
		}
		else if ( "<=".equals(operator) )
		{
			return Constants.OPERATOR_LESS_OR_EQUAL;
		}
		else if ( "=".equals(operator) )
		{
			return Constants.OPERATOR_EQUAL;
		}
		else if ( "\\=".equals(operator) )
		{
			return Constants.OPERATOR_NOT_EQUAL;
		}

		return "";
	}


	protected PrologAntiDriftBean retrievePrologAntiDriftBeanFromConstraint( final String conceptName
			, final Constraint constraint)
	{
		final String headerDriftQuery = Constants.DRIFT_HEADER;
		final String violation = PrologIntegrationConstants.VIOLATION;
		
		// it necessarily is a metric cosntrain
		final MetricConstraint metricConstraint = (MetricConstraint) constraint;
		final String metric = metricConstraint.getMetric().toLowerCase();
		final String operator = metricConstraint.getOperator();
		final String tamderaOperator = this.getNameOfOperator( operator );
		final String value = metricConstraint.getValue();

		final String template = getTemplateOfQuery( );
		final String query = String.format(template, headerDriftQuery
				,tamderaOperator,violation, metric, conceptName, value );
		
		return new PrologAntiDriftBean(query, conceptName, metricConstraint);

	}

	protected void _generateQuery( final ConceptDeclaration conceptDecl ) 
	{

		final String conceptName = conceptDecl.getName();


		for (Constraint constraint : conceptDecl.getConstraints() )
		{
			
			antiDriftQueries.add( retrievePrologAntiDriftBeanFromConstraint(conceptName, constraint) );
		}

		// constrainset
		for ( ConstraintSetDeclaration refConstraintSet : conceptDecl.getReferredConstraintSets() )  
		{
			for (Constraint constraint : refConstraintSet.getConstraints() )
			{
				antiDriftQueries.add( retrievePrologAntiDriftBeanFromConstraint(conceptName, constraint) );
			}
		}

	}

	public String getTemplateOfQuery (  )
	{
		String templateQuery = "%s_%s_%s('%s','%s',%s," + Constants.RESULT_QUERY_CLASSNAME 
				+"," + Constants.RESULT_QUERY_MEASURE + ").";

		return templateQuery;
	}




	public void generateQuery(final Object object) 
	{
		if (object instanceof ConceptDeclaration)
		{
			_generateQuery((ConceptDeclaration)object);
		} 
		else if (object instanceof RulesSpecification) 
		{
			_generateQuery((RulesSpecification)object);
		} 
		else 
		{
		}
	}


	public List<PrologQueryBean> getQueries() {
		return antiDriftQueries;
	}

	public void setQueries(List<PrologQueryBean> queries) {
		this.antiDriftQueries = queries;
	}
}
